﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TeamDev.JQuery;
using TeamDev.JQuery.Internals;
using System.Diagnostics.Contracts;
using System.Reflection;

public static class jqManipulationExtensions
{
  internal static jqExpression ExtendExpression(this jqExpression basicexpression, string verb, params string[] parameters)
  {
    StringBuilder methodname = new StringBuilder(string.Format(".{0}(", verb));
    if (parameters != null && parameters.Length > 0)
    {
      for (int i = 0; i < parameters.Length; i++)
      {
        if (i > 0)
          methodname.Append(",");
        methodname.AppendFormat("\"{{{0}}}\"", i);
      }
    }
    methodname.Append(")");

    if (parameters != null && parameters.Length > 0)
    { return new jqExpression(basicexpression + string.Format(methodname.ToString(), parameters)); }
    else
    { return new jqExpression(basicexpression + methodname.ToString()); }
  }  

  #region Attributes Manipulation

  public static jqExpression addClass(this jqExpression expr, string classname)
  {
    return expr.ExtendExpression("addClass", classname);
  }

  public static jqExpression attr(this jqExpression expr, string attrname)
  {
    return expr.ExtendExpression("attr", attrname);
  }

  public static jqExpression attr(this jqExpression expr, string attrname, string value)
  {
    return expr.ExtendExpression("attr", attrname, value);
  }

  public static jqExpression hasClass(this jqExpression expr, string classname)
  {
    return expr.ExtendExpression("hasClass", classname);
  }

  public static jqExpression html(this jqExpression expr)
  {
    return expr.ExtendExpression("html");
  }

  public static jqExpression html(this jqExpression expr, string htmlString)
  {
    return expr.ExtendExpression("html",htmlString);
  }

  public static jqExpression removeAttr(this jqExpression expr, string attrname)
  {
    return expr.ExtendExpression("removeAttr", attrname);
  }

  public static jqExpression removeClass(this jqExpression expr, string attrname)
  {
    return expr.ExtendExpression("removeClass", attrname);
  }

  public static jqExpression val(this jqExpression expr, string value)
  {
    return expr.ExtendExpression("val", value);
  }

  public static jqExpression val(this jqExpression expr)
  {
    return expr.ExtendExpression("val");
  }

  #endregion

  #region CSS Manipulation

  public static jqExpression css(this jqExpression expr, string propertyname)
  {
    return expr.ExtendExpression("css", propertyname);
  }

  public static jqExpression css(this jqExpression expr, string propertyname, string value)
  {
    return expr.ExtendExpression("css", propertyname, value);
  }

  public static jqExpression height(this jqExpression expr)
  {
    return expr.ExtendExpression("height");
  }

  public static jqExpression height(this jqExpression expr, string value)
  {
    return expr.ExtendExpression("height", value);
  }

  public static jqExpression innerHeight(this jqExpression expr)
  {
    return expr.ExtendExpression("innerHeight");
  }

  public static jqExpression innerWidth(this jqExpression expr)
  {
    return expr.ExtendExpression("innerWidth");
  }

  public static jqExpression offset(this jqExpression expr)
  {
    return expr.ExtendExpression("offset");
  }

  public static jqExpression offset(this jqExpression expr, string coordinates)
  {
    return expr.ExtendExpression("offset", coordinates);
  }

  public static jqExpression outerHeight(this jqExpression expr)
  {
    return expr.ExtendExpression("outerHeight");
  }

  public static jqExpression outerHeight(this jqExpression expr, bool includemargins)
  {
    return expr.ExtendExpression("outerHeight", includemargins.ToString());
  }

  public static jqExpression outerWidth(this jqExpression expr)
  {
    return expr.ExtendExpression("outerWidth");
  }

  public static jqExpression outerWidth(this jqExpression expr, bool includemargins)
  {
    return expr.ExtendExpression("outerWidth", includemargins.ToString());
  }

  public static jqExpression position(this jqExpression expr)
  {
    return expr.ExtendExpression("position");
  }

  public static jqExpression scrollLeft(this jqExpression expr)
  {
    return expr.ExtendExpression("scrollLeft");
  }

  public static jqExpression scrollLeft(this jqExpression expr, string value)
  {
    return expr.ExtendExpression("scrollLeft", value);
  }

  public static jqExpression scrollTop(this jqExpression expr)
  {
    return expr.ExtendExpression("scrollTop");
  }

  public static jqExpression scrollTop(this jqExpression expr, string value)
  {
    return expr.ExtendExpression("scrollTop", value);
  }

  public static jqExpression width(this jqExpression expr)
  {
    return expr.ExtendExpression("width");
  }

  public static jqExpression width(this jqExpression expr, string value)
  {
    return expr.ExtendExpression("width", value);
  }
  #endregion

  #region Data Manipulation

  public static jqExpression clearQueue(this jqExpression expr)
  {
    return expr.ExtendExpression("clearQueue");
  }

  public static jqExpression clearQueue(this jqExpression expr, string queuename)
  {
    return expr.ExtendExpression("clearQueue", queuename);
  }

  public static jqExpression queue(this jqExpression expr)
  {
    return expr.ExtendExpression("queue");
  }

  public static jqExpression queue(this jqExpression expr, string queuename)
  {
    return expr.ExtendExpression("queue", queuename);
  }

  public static jqExpression dequeue(this jqExpression expr)
  {
    return expr.ExtendExpression("dequeue");
  }

  public static jqExpression dequeue(this jqExpression expr, string queuename)
  {
    return expr.ExtendExpression("dequeue", queuename);
  }

  public static jqExpression data(this jqExpression expr, string key)
  {
    return expr.ExtendExpression("data", key);
  }

  public static jqExpression data(this jqExpression expr, string key, string value)
  {
    return expr.ExtendExpression("queue", key, value);
  }

  public static jqExpression removeData(this jqExpression expr, string key)
  {
    return expr.ExtendExpression("removeData", key);
  }

  public static jqExpression removeData(this jqExpression expr)
  {
    return expr.ExtendExpression("removeData");
  }

  #endregion

  #region Effects

  //.animate( properties, [ duration ], [ easing ], [ callback ] )
  //propertiesA map of CSS properties that the animation will move toward.
  //durationA string or number determining how long the animation will run.
  //easingA string indicating which easing function to use for the transition.
  //callbackA function to call once the animation is complete
  //TODO: bisogna implementare un overload che preveda un callback: http://api.jquery.com/animate/

  public static jqExpression animate(this jqExpression expr, string properties)
  {
    return expr.ExtendExpression("animate", properties);
  }

  public static jqExpression animate(this jqExpression expr, string properties, double duration)
  {
    return expr.ExtendExpression("animate", properties, duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
  }

  public static jqExpression animate(this jqExpression expr, string properties, Duration duration)
  {
    return expr.ExtendExpression("animate", properties, duration.ToString());
  }

  public static jqExpression animate(this jqExpression expr, string properties, Duration duration, string easing)
  {
    return expr.ExtendExpression("animate", properties,
                                            duration.ToString(),
                                            easing);
  }

  public static jqExpression animate(this jqExpression expr, string properties, double duration, string easing)
  {
    return expr.ExtendExpression("animate", properties,
                                            duration.ToString(System.Globalization.CultureInfo.InvariantCulture),
                                            easing);
  }


  //    .delay( duration, [ queueName ] )
  //durationAn integer indicating the number of milliseconds to delay execution of the next item in the queue.
  //queueNameA string containing the name of the queue. Defaults to fx, the standard effects queue.

  public static jqExpression delay(this jqExpression expr, int duration)
  {
    return expr.ExtendExpression("delay", duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
  }

  public static jqExpression delay(this jqExpression expr, int duration, string queueName)
  {
    return expr.ExtendExpression("delay", duration.ToString(System.Globalization.CultureInfo.InvariantCulture),
                                            queueName);
  }


  //    .fadeIn( [ duration ], [ callback ] )
  //durationA string or number determining how long the animation will run.
  //callbackA function to call once the animation is complete.

  public static jqExpression fadeIn(this jqExpression expr)
  {
    return expr.ExtendExpression("falden");
  }

  public static jqExpression fadeIn(this jqExpression expr, double duration)
  {
    return expr.ExtendExpression("fadeIn", duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
  }

  public static jqExpression fadeIn(this jqExpression expr, Duration duration)
  {
    return expr.ExtendExpression("fadeIn", duration.ToString());
  }

  public static jqExpression fadeIn(this jqExpression expr, double duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".fadeIn(\"{0}\",{1})", duration.ToString(System.Globalization.CultureInfo.InvariantCulture), (string)callback));
  }

  public static jqExpression fadeIn(this jqExpression expr, Duration duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".fadeIn(\"{0}\",{1})", duration, (string)callback));
  }


  //    .fadeOut( [ duration ], [ callback ] )
  //durationA string or number determining how long the animation will run.
  //callbackA function to call once the animation is complete.

  public static jqExpression fadeOut(this jqExpression expr)
  {
    return expr.ExtendExpression("fadeOut");
  }

  public static jqExpression fadeOut(this jqExpression expr, double duration)
  {
    return expr.ExtendExpression("fadeOut", duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
  }

  public static jqExpression fadeOut(this jqExpression expr, Duration duration)
  {
    return expr.ExtendExpression("fadeOut", duration.ToString());
  }

  public static jqExpression fadeOut(this jqExpression expr, double duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".fadeOut(\"{0}\",{1})", duration.ToString(System.Globalization.CultureInfo.InvariantCulture), (string)callback));
  }

  public static jqExpression fadeOut(this jqExpression expr, Duration duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".fadeOut(\"{0}\",{1})", duration, (string)callback));
  }


  //    .fadeTo( duration, opacity, [ callback ] )
  //durationA string or number determining how long the animation will run.
  //opacityA number between 0 and 1 denoting the target opacity.
  //callbackA function to call once the animation is complete.

  public static jqExpression fadeTo(this jqExpression expr, double duration, double opacity)
  {
    InputValidator.Assert(opacity >= 0.0 && opacity <= 1.0, "Duration must be between 0 and 1");
    return expr.ExtendExpression("fadeTo", duration.ToString(System.Globalization.CultureInfo.InvariantCulture),
                                            opacity.ToString());
  }

  public static jqExpression fadeTo(this jqExpression expr, Duration duration, double opacity)
  {
    InputValidator.Assert(opacity >= 0.0 && opacity <= 1.0, "Duration must be between 0 and 1");
    return expr.ExtendExpression("fadeTo", duration.ToString(),
                                            opacity.ToString());
  }

  public static jqExpression fadeTo(this jqExpression expr, double duration, double opacity, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".fadeTo(\"{0}\",{1},\"{2}\")", duration.ToString(System.Globalization.CultureInfo.InvariantCulture),
                                                                                    opacity.ToString(System.Globalization.CultureInfo.InvariantCulture),
                                                                                        (string)callback));
  }

  public static jqExpression fadeTo(this jqExpression expr, Duration duration, double opacity, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".fadeTo(\"{0}\",{1},\"{2}\")", duration.ToString(),
                                                                                    opacity.ToString(System.Globalization.CultureInfo.InvariantCulture),
                                                                                        (string)callback));
  }


  //      .hide()
  //      .hide( duration, [ callback ] )
  //      durationA string or number determining how long the animation will run.
  //      callbackA function to call once the animation is complete.

  public static jqExpression hide(this jqExpression expr)
  {
    return expr.ExtendExpression("hide");
  }

  public static jqExpression hide(this jqExpression expr, double duration)
  {
    return expr.ExtendExpression("hide", duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
  }

  public static jqExpression hide(this jqExpression expr, Duration duration)
  {
    return expr.ExtendExpression("hide", duration.ToString());
  }

  public static jqExpression hide(this jqExpression expr, double duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".hide(\"{0}\",{1})", duration.ToString(System.Globalization.CultureInfo.InvariantCulture), (string)callback));
  }

  public static jqExpression hide(this jqExpression expr, Duration duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".hide(\"{0}\",{1})", duration, (string)callback));
  }


  //.show()
  //.show( duration, [ callback ] )
  //durationA string or number determining how long the animation will run.
  //callbackA function to call once the animation is complete.

  public static jqExpression show(this jqExpression expr)
  {
    return expr.ExtendExpression("show");
  }

  public static jqExpression show(this jqExpression expr, double duration)
  {
    return expr.ExtendExpression("show", duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
  }

  public static jqExpression show(this jqExpression expr, Duration duration)
  {
    return expr.ExtendExpression("show", duration.ToString());
  }

  public static jqExpression show(this jqExpression expr, double duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".show(\"{0}\",{1})", duration.ToString(System.Globalization.CultureInfo.InvariantCulture), (string)callback));
  }

  public static jqExpression show(this jqExpression expr, Duration duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".show(\"{0}\",{1})", duration, (string)callback));
  }


  //    .slideDown( [ duration ], [ callback ] )
  //durationA string or number determining how long the animation will run.
  //callbackA function to call once the animation is complete.

  public static jqExpression slideDown(this jqExpression expr)
  {
    return expr.ExtendExpression("slideDown");
  }

  public static jqExpression slideDown(this jqExpression expr, double duration)
  {
    return expr.ExtendExpression("slideDown", duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
  }

  public static jqExpression slideDown(this jqExpression expr, Duration duration)
  {
    return expr.ExtendExpression("slideDown", duration.ToString());
  }

  public static jqExpression slideDown(this jqExpression expr, double duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".slideDown(\"{0}\",{1})", duration.ToString(System.Globalization.CultureInfo.InvariantCulture), (string)callback));
  }

  public static jqExpression slideDown(this jqExpression expr, Duration duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".slideDown(\"{0}\",{1})", duration, (string)callback));
  }


  //    .slideToggle( [ duration ], [ callback ] )
  //durationA string or number determining how long the animation will run.
  //callbackA function to call once the animation is complete.

  public static jqExpression slideToggle(this jqExpression expr)
  {
    return expr.ExtendExpression("slideToggle");
  }

  public static jqExpression slideToggle(this jqExpression expr, double duration)
  {
    return expr.ExtendExpression("slideToggle", duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
  }

  public static jqExpression slideToggle(this jqExpression expr, Duration duration)
  {
    return expr.ExtendExpression("slideToggle", duration.ToString());
  }

  public static jqExpression slideToggle(this jqExpression expr, double duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".slideToggle(\"{0}\",{1})", duration.ToString(System.Globalization.CultureInfo.InvariantCulture), (string)callback));
  }

  public static jqExpression slideToggle(this jqExpression expr, Duration duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".slideToggle(\"{0}\",{1})", duration, (string)callback));
  }


  //    .slideUp( [ duration ], [ callback ] )
  //durationA string or number determining how long the animation will run.
  //callbackA function to call once the animation is complete.

  public static jqExpression slideUp(this jqExpression expr)
  {
    return expr.ExtendExpression("slideUp");
  }

  public static jqExpression slideUp(this jqExpression expr, double duration)
  {
    return expr.ExtendExpression("slideUp", duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
  }

  public static jqExpression slideUp(this jqExpression expr, Duration duration)
  {
    return expr.ExtendExpression("slideUp", duration.ToString());
  }

  public static jqExpression slideUp(this jqExpression expr, double duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".slideUp(\"{0}\",{1})", duration.ToString(System.Globalization.CultureInfo.InvariantCulture), (string)callback));
  }

  public static jqExpression slideUp(this jqExpression expr, Duration duration, jsFunctionBlock callback)
  {
    return new jqExpression(expr + string.Format(".slideUp(\"{0}\",{1})", duration, (string)callback));
  }


  //    .stop( [ clearQueue ], [ jumpToEnd ] )
  //clearQueueA Boolean indicating whether to remove queued animation as well. Defaults to false.
  //jumpToEndA Boolean indicating whether to complete the current animation immediately. Defaults to false.

  public static jqExpression stop(this jqExpression expr)
  {
    return expr.ExtendExpression("stop");
  }

  public static jqExpression stop(this jqExpression expr, bool clearQueue)
  {
    return expr.ExtendExpression("stop", clearQueue.ToString());
  }

  public static jqExpression stop(this jqExpression expr, bool clearQueue, bool jumpToEnd)
  {
    return expr.ExtendExpression("stop", clearQueue.ToString(), jumpToEnd.ToString());
  }


  //    .toggle( handler(eventObject), handler(eventObject), [ handler(eventObject) ] )
  //handler(eventObject)A function to execute every even time the element is clicked.
  //handler(eventObject)A function to execute every odd time the element is clicked.
  //handler(eventObject)Additional handlers to cycle through after clicks.

  public static jqExpression toggle(this jqExpression expr, jsFunctionBlock evenhandler)
  {
    return new jqExpression(expr + string.Format(".toggle({0})", (string)evenhandler));
  }

  public static jqExpression toggle(this jqExpression expr, jsFunctionBlock evenhandler, jsFunctionBlock oddhandler)
  {
    return new jqExpression(expr + string.Format(".toggle({0},{1})", (string)evenhandler, (string)oddhandler));
  }

  public static jqExpression toggle(this jqExpression expr, jsFunctionBlock evenhandler, jsFunctionBlock oddhandler, jsFunctionBlock afterhandler)
  {
    return new jqExpression(expr + string.Format(".toggle({0},{1},{2})", (string)evenhandler, (string)oddhandler, (string)afterhandler));
  }

  #endregion

  #region Events


  //.bind( eventType, [ eventData ], handler(eventObject) )
  //eventTypeA string containing one or more JavaScript event types, such as "click" or "submit," or custom event names.
  //eventDataA map of data that will be passed to the event handler.
  //handler(eventObject)A function to execute each time the event is triggered.
  //eventsA map of one or more JavaScript event types and functions to execute for them.
  //TODO: controllare il ".bind( events )" ed implementarlo: http://api.jquery.com/bind/
  public static jqExpression bind(this jqExpression expr, string eventType, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".bind(\"{0}\",{1})", eventType, (string)eventObjecthandler));
  }

  public static jqExpression bind(this jqExpression expr, string eventType, object eventdata, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".bind(\"{0}\",{2},{1})", eventType, (string)eventObjecthandler, InternalUtils.ExtractData(eventdata)));
  }


  //    .blur( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.blur()
  public static jqExpression blur(this jqExpression expr)
  {
    return expr.ExtendExpression("blur");
  }

  public static jqExpression blur(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".blur({0})", (string)eventObjecthandler));
  }


  //    .change( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.change()
  public static jqExpression change(this jqExpression expr)
  {
    return expr.ExtendExpression("change");
  }

  public static jqExpression change(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".change({0})", (string)eventObjecthandler));
  }


  //    .click( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.click()
  public static jqExpression click(this jqExpression expr)
  {
    return expr.ExtendExpression("click");
  }

  public static jqExpression click(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".click({0})", (string)eventObjecthandler));
  }


  //.dblclick( handler(eventObject) )
  //handler(eventObject) A function to execute each time the event is triggered.
  //.dblclick()
  public static jqExpression dblclick(this jqExpression expr)
  {
    return expr.ExtendExpression("dblclick");
  }

  public static jqExpression dblclick(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".dblclick({0})", (string)eventObjecthandler));
  }



  //.delegate( selector, eventType, handler )
  //selector A selector to filter the elements that trigger the event.
  //eventType A string containing one or more space-separated JavaScript event types, such as "click" or "keydown," or custom event names.
  //handler A function to execute at the time the event is triggered.

  //    .delegate( selector, eventType, eventData, handler )
  //selector A selector to filter the elements that trigger the event.
  //eventType A string containing one or more space-separated JavaScript event types, such as "click" or "keydown," or custom event names.
  //eventData A map of data that will be passed to the event handler.
  //handler A function to execute at the time the event is triggered.
  public static jqExpression event_delegate(this jqExpression expr, jqBasicSelector selector, string eventType, jsFunctionBlock handlerAhandler)
  {
    return new jqExpression(expr + string.Format(".event_delegate({0},\"{1}\",{2})", selector.Filter, eventType, (string)handlerAhandler));
  }

  public static jqExpression event_delegate(this jqExpression expr, jqBasicSelector selector, string eventType, object eventdata, jsFunctionBlock handlerAhandler)
  {
    return new jqExpression(expr + string.Format(".event_delegate({0},\"{1}\",{2},{3})", selector.Filter, eventType, InternalUtils.ExtractData(eventdata), (string)handlerAhandler));
  }


  //    .die( eventType, [ handler ] )
  //eventTypeA string containing a JavaScript event type, such as click or keydown.
  //handler The function that is to be no longer executed.
  //    .die()
  public static jqExpression die(this jqExpression expr)
  {
    return expr.ExtendExpression("die");
  }

  public static jqExpression die(this jqExpression expr, string eventType)
  {
    return expr.ExtendExpression("die", eventType);

  }

  public static jqExpression die(this jqExpression expr, string eventType, jsFunctionBlock handler)
  {
    return new jqExpression(expr + string.Format(".die(\"{0}\",{1})", eventType, (string)handler));
  }


  //    .error( handler(eventObject) )
  //handler(eventObject) A function to execute when the event is triggered.
  public static jqExpression error(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".error({0})", (string)eventObjecthandler));
  }


  //.focus( handler(eventObject) )
  //handler(eventObject) A function to execute each time the event is triggered.
  //.focus()
  public static jqExpression focus(this jqExpression expr)
  {
    return expr.ExtendExpression("focus");
  }

  public static jqExpression focus(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".focus({0})", (string)eventObjecthandler));
  }

  //    .focusin( handler(eventObject) )
  //handler(eventObject) A function to execute each time the event is triggered.
  public static jqExpression focusin(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".focusin({0})", (string)eventObjecthandler));
  }

  //    .focusout( handler(eventObject) )
  //handler(eventObject) A function to execute each time the event is triggered.
  public static jqExpression focusout(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".focusout({0})", (string)eventObjecthandler));
  }

  //    .hover( handlerIn(eventObject), handlerOut(eventObject) )
  //handlerIn(eventObject) A function to execute when the mouse pointer enters the element.
  //handlerOut(eventObject) A function to execute when the mouse pointer leaves the element.
  public static jqExpression hover(this jqExpression expr, jsFunctionBlock eventObjecthandlerIn, jsFunctionBlock eventObjecthandlerOut)
  {
    return new jqExpression(expr + string.Format(".hover({0},{1})", (string)eventObjecthandlerIn, (string)eventObjecthandlerOut));
  }


  //.keydown( handler(eventObject) )
  //handler(eventObject) A function to execute each time the event is triggered.
  //.keydown()
  public static jqExpression keydown(this jqExpression expr)
  {
    return expr.ExtendExpression("keydown");
  }

  public static jqExpression keydown(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".keydown({0})", (string)eventObjecthandler));
  }


  //.keypress( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.keypress()
  public static jqExpression keypress(this jqExpression expr)
  {
    return expr.ExtendExpression("keypress");
  }

  public static jqExpression keypress(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".keypress({0})", (string)eventObjecthandler));
  }


  //.keyup( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.keyup()
  public static jqExpression keyup(this jqExpression expr)
  {
    return expr.ExtendExpression("keyup");
  }

  public static jqExpression keyup(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".keyup({0})", (string)eventObjecthandler));
  }


  //.live( eventType, handler )
  //eventTypeA string containing a JavaScript event type, such as "click" or "keydown." As of jQuery 1.4 the string can contain multiple,
  //space-separated event types or custom event names, as well.
  //handlerA function to execute at the time the event is triggered.

  //.live( eventType, eventData, handler )
  //eventTypeA string containing a JavaScript event type, such as "click" or "keydown." As of jQuery 1.4 the string can contain multiple,
  //space-separated event types or custom event names, as well.
  //eventDataA map of data that will be passed to the event handler.
  //handlerA function to execute at the time the event is triggered.
  public static jqExpression live(this jqExpression expr, string eventType, jsFunctionBlock handlerAhandler)
  {
    return new jqExpression(expr + string.Format(".live(\"{0}\",{1})", eventType, (string)handlerAhandler));
  }

  public static jqExpression live(this jqExpression expr, string eventType, object eventdata, jsFunctionBlock handlerAhandler)
  {
    return new jqExpression(expr + string.Format(".live(\"{0}\",{1},{2})", eventType, InternalUtils.ExtractData(eventdata), (string)handlerAhandler));
  }


  //    .load( handler(eventObject) )
  //handler(eventObject)A function to execute when the event is triggered.
  public static jqExpression load(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".load({0})", (string)eventObjecthandler));
  }


  //.mousedown( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.mousedown()
  public static jqExpression mousedown(this jqExpression expr)
  {
    return expr.ExtendExpression("mousedown");
  }

  public static jqExpression mousedown(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".mousedown({0})", (string)eventObjecthandler));
  }


  //    .mouseenter( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.mouseenter()
  public static jqExpression mouseenter(this jqExpression expr)
  {
    return expr.ExtendExpression("mouseenter");
  }

  public static jqExpression mouseenter(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".mouseenter({0})", (string)eventObjecthandler));
  }


  //    .mouseleave( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.mouseleave()
  public static jqExpression mouseleave(this jqExpression expr)
  {
    return expr.ExtendExpression("mouseleave");
  }

  public static jqExpression mouseleave(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".mouseleave({0})", (string)eventObjecthandler));
  }


  //    .mousemove( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.mousemove()
  public static jqExpression mousemove(this jqExpression expr)
  {
    return expr.ExtendExpression("mousemove");
  }

  public static jqExpression mousemove(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".mousemove({0})", (string)eventObjecthandler));
  }


  //    .mouseout( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.mouseout()
  public static jqExpression mouseout(this jqExpression expr)
  {
    return expr.ExtendExpression("mouseout");
  }

  public static jqExpression mouseout(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".mouseout({0})", (string)eventObjecthandler));
  }


  //    .mouseover( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.mouseover()
  public static jqExpression mouseover(this jqExpression expr)
  {
    return expr.ExtendExpression("mouseover");
  }

  public static jqExpression mouseover(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".mouseover({0})", (string)eventObjecthandler));
  }


  //    .mouseup( handler(eventObject) )
  //handler(eventObject) A function to execute each time the event is triggered.
  //.mouseup()
  public static jqExpression mouseup(this jqExpression expr)
  {
    return expr.ExtendExpression("mouseup");
  }

  public static jqExpression mouseup(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".mouseup({0})", (string)eventObjecthandler));
  }


  //    .one( eventType, [ eventData ], handler(eventObject) )
  //eventType A string containing one or more JavaScript event types, such as "click" or "submit," or custom event names.
  //eventData A map of data that will be passed to the event handler.
  //handler(eventObject) A function to execute at the time the event is triggered.
  public static jqExpression one(this jqExpression expr, string eventType, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".one(\"{0}\",{1})", eventType, (string)eventObjecthandler));
  }

  public static jqExpression one(this jqExpression expr, string eventType, object eventdata, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".one(\"{0}\",{1},{2})", eventType, InternalUtils.ExtractData(eventdata), (string)eventObjecthandler));
  }

  //TODO: controllare ed implementare jQuery.proxy(): http://api.jquery.com/jQuery.proxy/


  //.ready( handler )
  //handler A function to execute after the DOM is ready.
  public static jqExpression ready(this jqExpression expr, jsFunctionBlock handlerhandler)
  {
    return new jqExpression(expr + string.Format(".ready({1})", (string)handlerhandler));
  }


  //.resize( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.resize()
  public static jqExpression resize(this jqExpression expr)
  {
    return expr.ExtendExpression("resize");
  }

  public static jqExpression resize(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".resize({1})", (string)eventObjecthandler));
  }


  //    .scroll( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.scroll()
  public static jqExpression scroll(this jqExpression expr)
  {
    return expr.ExtendExpression("scroll");
  }

  public static jqExpression scroll(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".scroll({1})", (string)eventObjecthandler));
  }


  //    .select( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.select()
  public static jqExpression select(this jqExpression expr, jsFunctionBlock handlerhandler)
  {
    return new jqExpression(expr + string.Format(".select({1})", (string)handlerhandler));
  }


  //.submit( handler(eventObject) )
  //handler(eventObject)A function to execute each time the event is triggered.
  //.submit()
  public static jqExpression submit(this jqExpression expr)
  {
    return expr.ExtendExpression("submit");
  }

  public static jqExpression submit(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".submit({1})", (string)eventObjecthandler));
  }


  //    .trigger( eventType, extraParameters )
  //eventType A string containing a JavaScript event type, such as click or submit.
  //extraParameters An array of additional parameters to pass along to the event handler.
  public static jqExpression trigger(this jqExpression expr, string eventType, params string[] extraParameters)
  {
    return new jqExpression(expr + string.Format(".trigger(\"{0}\",{1})", extraParameters));
  }


  //    .trigger( eventType, extraParameters )
  //eventType A string containing a JavaScript event type, such as click or submit.
  //extraParameters An array of additional parameters to pass along to the event handler.
  public static jqExpression triggerHandler(this jqExpression expr, string eventType, params string[] extraParameters)
  {
    return new jqExpression(expr + string.Format(".triggerHandler(\"{0}\",{1})", extraParameters));
  }


  //    .unbind( eventType, handler(eventObject) )
  //eventTypeA string containing a JavaScript event type, such as click or submit.
  //handler(eventObject)The function that is to be no longer executed.
  //TODO: controllare ed implementare .unbind(event): http://api.jquery.com/unbind/
  public static jqExpression unbind(this jqExpression expr, string eventType, string eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".unbind(\"{0}\",{1})", eventObjecthandler));
  }


  //.undelegate()

  //    .undelegate( selector, eventType )
  //selector A selector which will be used to filter the event results.
  //eventType A string containing a JavaScript event type, such as "click" or "keydown"

  //    .undelegate( selector, eventType, handler )
  //selector A selector which will be used to filter the event results.
  //eventType A string containing a JavaScript event type, such as "click" or "keydown"
  //handler A function to execute at the time the event is triggered.
  public static jqExpression undelegate(this jqExpression expr)
  {
    return expr.ExtendExpression("undelegate");
  }

  public static jqExpression undelegate(this jqExpression expr, jqBasicSelector selector, string eventType)
  {
    return new jqExpression(expr + string.Format(".undelegate({0},\"{1}\")", selector.Filter, eventType));
  }

  public static jqExpression undelegate(this jqExpression expr, jqBasicSelector selector, string eventType, string handlerhandler)
  {
    return new jqExpression(expr + string.Format(".undelegate({0},\"{1}\",{2},)", selector.Filter, eventType, handlerhandler));
  }


  //    .unload( handler(eventObject) )
  //handler(eventObject)A function to execute when the event is triggered.
  public static jqExpression unload(this jqExpression expr, jsFunctionBlock eventObjecthandler)
  {
    return new jqExpression(expr + string.Format(".unload({1})", (string)eventObjecthandler));
  }
  #endregion
}


public enum Duration
{
  fast,
  slow
}





